/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 */
package Search;

import javax.naming.directory.SearchControls;
import org.geotools.graph.structure.Graph;
import org.geotools.graph.structure.GraphVisitor;
import org.geotools.graph.structure.Graphable;
import org.geotools.graph.traverse.GraphIterator;
import org.geotools.graph.traverse.GraphTraversal;
import org.geotools.graph.traverse.GraphWalker;

/**
 * A basic implementation of GraphTraversal.
 *
 * @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net
 *
 * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/extension/graph/src/main/java/org/geotools/graph/traverse/basic/BasicGraphTraversal.java $
 */
public class BasicGraphTraversal implements GraphTraversal {

  /** the graph being iterated over **/
  private Graph m_graph;

  /** the walker being iterated over the graph **/
  private GraphWalker m_walker;

  /** the iterator specifying the order in which to visit components of
      the graph during the traversal **/
  private GraphIterator m_iterator;

  /**
   * Constructs a new graph traversal.
   *
   * @param graph The graph being traversed.
   * @param walker The walker being traversed over the components of the graph.
   * @param iterator The iterator specifying the order in which to visit
   *        components of the graph.
   */
  public BasicGraphTraversal(
    Graph graph, GraphWalker walker, GraphIterator iterator
  ) {
    m_graph = graph;
    m_walker = walker;
    setIterator(iterator);
  }

  /**
   * @see GraphTraversal#setGraph(Graph)
   */
  public void setGraph(Graph graph) {
    m_graph = graph;
  }

  /**
   * @see GraphTraversal#getGraph()
   */
  public Graph getGraph() {
    return(m_graph);
  }

  /**
   * Sets the iterator and intializes it.
   *
   * @see GraphIterator#init(Graph)
   * @see GraphTraversal#setIterator(GraphIterator)
   */
  public void setIterator(GraphIterator iterator) {
    m_iterator = iterator;
    m_iterator.setTraversal(this);
    m_iterator.init(m_graph, this);
  }

  /**
   * @see GraphTraversal#getIterator()
   */
  public GraphIterator getIterator() {
    return(m_iterator);
  }

  /**
   * @see GraphTraversal#setWalker(GraphWalker)
   */
  public void setWalker(GraphWalker walker) {
    m_walker = walker;
  }

  /**
   * @see GraphTraversal#getWalker()
   */
  public GraphWalker getWalker() {
    return(m_walker);
  }

  /**
   * Resets the visited flag and counts of all nodes of the graph.
   *
   * @see GraphTraversal#init()
   */
  public void init() {
    //initialize the nodes of the graph
    m_graph.visitNodes(
      new GraphVisitor() {
        public int visit(Graphable component) {
          component.setVisited(false);
          component.setCount(0);
            System.out.println(component.getCount());
          return(0);
        }
      }
    );
  }

  /**
   * Upon each iteration of the traversal, a component is returned from the
   * iterator and passed to the visitor. The traversal interprets the return
   * codes from the walker and performs the following actions. <BR>
   * <BR>
   * <TABLE border="1" width="60%" style="font-family:Arial;font-size=10pt">
   *   <TH width="20%">Code</TH>
   *   <TH width="40%">Action Performed</TH>
   *   <TR>
   *     <TD align="center">CONTINUE</TD>
   *     <TD>The traversal instructs the iterator to continue and starts the
   *         next stage of iteration.</TD>
   *   </TR>
   *  <TR>
   *     <TD align="center">SUSPEND</TD>
   *     <TD>The traversal instructs the iterator to continue but does not start
   *         the next stage of iteration, returning from traverse().</TD>
   *  </TR>
   *  <TR>
   *     <TD align="center">KILL_BRANCH</TD>
   *     <TD>The traversal instructs the iterator to kill the current branch
   *         and starts the next stage of iteration.</TD>
   *   </TR>
   *  <TR>
   *     <TD align="center">STOP</TD>
   *     <TD>The traversal does not instruct the iterator to continue and
   *         does not start the next of iteration, returning from traverse()
   *     </TD>
   *   </TR>
   * </TABLE>
   *
   * @see GraphTraversal#traverse()
   */
  public void traverse() {
    Graphable current;

    //get next component from iterator, null means stop
O:  while((current = m_iterator.next(this)) != null) {
      setVisited(current, true);

      //pass the component to the visitor
      switch(m_walker.visit(current, null)) {
        case CONTINUE:
          //signal iterator to continue from this point and start next
          // iteration of traversal
          m_iterator.cont(current,this);
          continue;

        case SUSPEND:
          //signal iterator to continue from this point, but do not start
          // next iteration
          m_iterator.cont(current,this);
          return;

        case KILL_BRANCH:
          //signal iterator to kill branch at this point and start next
          //iteration
          m_iterator.killBranch(current,this);
          continue;

        case STOP:
          //stop traversal
          break O;

        default:
          //illegal return value from walker
          throw new IllegalStateException(
            "Unrecognized return value from GraphWalker"
          );
      }
    }

    //traversal complete, signal to walker
    m_walker.finish();
  }

  public void setVisited(Graphable g, boolean visited) {
    g.setVisited(visited);
  }

  public boolean isVisited(Graphable g) {
    return(g.isVisited());
  }
}
